package FlowGraph.StatementInfo;

import java.util.*;

import antlr.collections.AST;

import util.Line;
import FlowGraph.*;
import FlowGraph.SSA.*;

//////////////////////////////////////////////////////////////////////////
//// StatementInfo
/**
        Uma classe base para dados associados a um statement.

@author Ivan Jeukens
@version v 0.1 12/06/2002
*/
public class StatementInfo {

    public static final int UNDEF = 0;
    public static final int VARDEF = 1;

    public StatementInfo() {
        _label = null;
        _type = UNDEF;

        _usedVars = new HashMap();
        _definedVars = new HashMap();
        
        _indexedVarUse = new LinkedList();
        _indexedVarDef = new LinkedList();
    }

    public StatementInfo(FlowGraphNode node, AST statement) {
        this();
        _statement = statement;
        _fgNode = node;
    }

    public StatementInfo(FlowGraphNode node, AST statement, int type) {
        this();
        _type = type;
        _statement = statement;
        _fgNode = node;
    }

    ///////////////////////////////////////////////////////////////////
    ////                        public methods                     //// 

    public void setType(int type) {
        _type = type;
    }

    public int getType() {
        return _type;
    }

// Label de BB
    public void setLabel(String label) {
        _label = label;
    }
    
    public String getLabel() {
        return _label;
    }

    public AST getStatement() {
        return _statement;
    }

    public void setStatement(AST stat) {
        _statement = stat;
    }
    
    public void setNode(FlowGraphNode node) {
        _fgNode = node;
    }

    public FlowGraphNode getNode() {
        return _fgNode;
    }

// A linha do texto do codigo.
    public void setLine(Line l) {
        _line = l;
    }
    
    public Line getLine() {
        return _line;
    }
    
    public void addUsedVar(VariableInfo var, AST stat) {
        LinkedList l = (LinkedList) _usedVars.get(var);
        if(l == null) {
            l = new LinkedList();
            _usedVars.put(var, l);
        }
        l.add(stat);
    }
    
    public Iterator usedVarsIterator() {
        return _usedVars.keySet().iterator();
    }

    public LinkedList getUses(VariableInfo var) {
        return (LinkedList) _usedVars.get(var);
    }

    public void addDefinedVar(VariableInfo var, AST stat) {
        LinkedList l = (LinkedList) _definedVars.get(var);
        if(l == null) {
            l = new LinkedList();
            _definedVars.put(var, l);
        }
        l.add(stat);
    }

    public Iterator definedVarsIterator() {
        return _definedVars.keySet().iterator();
    }

    public LinkedList getDefs(VariableInfo var) {
        return (LinkedList) _definedVars.get(var);
    }

    // Adiciona uma var_index (produto do rename do SSA) nesse statement.
    public void addIndexedVarUse(int index, VariableLocation loc, 
            VariableInfo info) {
        IndexedVarInfo ivi = new IndexedVarInfo(index, loc, info);
        _indexedVarUse.add(ivi);
    }
    
    public Iterator useIndexedVarIterator() {
        return _indexedVarUse.iterator();
    }

    public void removeIndexedVarUse(int index, VariableLocation loc,
            VariableInfo info) {
        for(int i = 0;i < _indexedVarUse.size();i++) {
            IndexedVarInfo ivi = (IndexedVarInfo) _indexedVarUse.get(i);
            if(ivi.index == index && ivi.loc == loc && ivi.varinfo == info) {
                _indexedVarUse.remove(ivi);
                return;
            }
        }
    }

    public void addIndexedVarDef(int index, VariableLocation loc, 
            VariableInfo info) {
        IndexedVarInfo ivi = new IndexedVarInfo(index, loc, info);
        _indexedVarDef.add(ivi);
    }

    public Iterator defIndexedVarIterator() {
        return _indexedVarDef.iterator();
    }

    // COXA: so pra depurar.
    public void printIndexedVars() {
        System.out.println("Indexed vars for " + _statement.toStringTree());
        System.out.println("Uses:");
        if(_indexedVarUse != null) {
            for(int i = 0;i < _indexedVarUse.size();i++) {
                IndexedVarInfo ivi = (IndexedVarInfo) _indexedVarUse.get(i);
                System.out.println(ivi.varinfo + "_" + ivi.index);
            }
        }

        System.out.println("Defs:");
        if(_indexedVarDef != null) {
            for(int i = 0;i < _indexedVarDef.size();i++) {
                IndexedVarInfo ivi = (IndexedVarInfo) _indexedVarDef.get(i);
                System.out.println(ivi.varinfo + "_" + ivi.index);
            }
        }
    }

    public String toString() {
        return new String("statment info for " + _fgNode);
    }

    ///////////////////////////////////////////////////////////////////
    ////                      private variables                    ////

    private AST _statement;
    private FlowGraphNode _fgNode;

    private int _type;
    private String _label;
    private Line _line;

    // Usado pelo algoritmo de rename de var do SSA
    // O key do map e um VariableInfo. Cada valor e uma lista
    // contendo o ponto do AST. Esses maps ficam invalidos
    // apos rodar os algoritmos de simplificacao!!!
    private HashMap _usedVars;
    private HashMap _definedVars;

    private LinkedList _indexedVarUse;
    private LinkedList _indexedVarDef;
}
